﻿//	现代编译器会为了尽可能提高程序的效率，在不影响正确性的情况下会尽可能减少一些传参和传返回值的过程中可以省略的拷贝。
//	如何优化C++标准并没有严格规定，各个编译器会根据情况自行处理。
//	当前主流的相对新一点的编译器对于连续一个表达式步骤中的连续拷贝会进行合并优化，有些更新更“激进”的编译器还会进行跨行跨表达式的合并优化。
//	linux下可以将下面代码拷贝到test.cpp文件，编译时用 g++ test.cpp - fno - elide - constructors 的方式关闭构造相关的优化。


#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& aa)
		:_a1(aa._a1)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a1 = aa._a1;
		}
		return *this;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1 = 1;
};
void f1(A aa)
{
}
A f2()
{
	A aa;
	return aa;
}
int main()
{
	// 传值传参
	// 构造+拷⻉构造
	A aa1;
	f1(aa1);
	cout << endl;
	// 隐式类型，连续构造+拷⻉构造->优化为直接构造
	f1(1);
	// 一个表达式中，连续构造+拷⻉构造->优化为⼀个构造
	f1(A(2));
	cout << endl;

	cout << "***********************************************" << endl;

	// 传值返回
	// 不优化的情况下传值返回，编译器会⽣成⼀个拷⻉返回对象的临时对象作为函数调⽤表达式的返回值
		// ⽆优化 （vs2019 debug）
		// ⼀些编译器会优化得更厉害，将构造的局部对象和拷⻉构造的临时对象优化为直接构造（vs2022 debug）
	A aa2 = f2();
	cout << endl;
	// 返回时⼀个表达式中，连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 （vs2019 debug）
	// ⼀些编译器会优化得更厉害，进⾏跨⾏合并优化，将构造的局部对象aa和拷⻉的临时对象和接收返回值对象aa2优化为⼀个直接构造。（vs2022 debug）
	A aa2 = f2();
	cout << endl;
	// ⼀个表达式中，开始构造，中间拷⻉构造+赋值重载->⽆法优化（vs2019 debug）
	// ⼀些编译器会优化得更厉害，进⾏跨⾏合并优化，将构造的局部对象aa和拷⻉临时对象合并为⼀个直接构造（vs2022 debug）
	aa1 = f2();
	cout << endl;
	return 0;
}


//以后写代码时,优先考虑使用 匿名对象 或 类型转换 来传参,不推荐有名对象
//接收传值返回时,优先考虑使用 A a = f() 构造来接收

